import java.util.Calendar;
import java.util.Timer;

import javax.xml.bind.JAXBException;

public class Improvise {
	public int count=0;
	public String name=null; // temporary
	public String[] styles = new String[20]; // TODO: store all loaded styles,strength 
	public int[] styleStrengths = new int[20];
	public int stylePointer=0;
	public int scale=0;
	public boolean major=true;
	public int[] pitchProbArray = new int[1];
	public int[] notesInput = new int[1];
	public int[] notesOutput = new int[1];
	public int[] volumeOutput = new int[1];
	public int[] durationOutput = new int[1];
	public int pitchChoice;
	public int pitch;
	public int lastPitch=0;
	public int lastPitchTr=0;
	public Timer timer;
	public TimerNewNote timerNewNote;
	public int waitTime = 100;
	public boolean stop = true;
	public boolean listening = false;
	public long lastInputOnset=0;
	public boolean playing=false;
	public boolean soloing=false;// human player is soloing?
	public boolean learnSoloing=false;
	
	public int pointer = 3;
	
	public void start() throws JAXBException {
		System.out.println("improvising... again");
		if (stop==false){
			decideStyle();
			int[] notes = null;
			int[] volume = null;
			int[] duration = null;
			if (name.equalsIgnoreCase("me")){
				System.out.println("me test successful");
				notes = Main.stats.notes;
				volume = Main.stats.volume;
				duration = Main.stats.duration;
				
			}
			else {
				notes = XML.getNotes(name);
				volume = XML.getVolume(name);
				duration = XML.getDuration(name);
			}
			if (count==0&&notes.length>6){
				int choice = (int) (Math.random()*(notes.length-4))+1;
				
				Object[] noteArray = {notes[choice]+scale,volume[choice]};
				int[] noteArrayInt = {notes[choice]+scale,volume[choice]};
				
				lastPitch=notes[choice]+scale;
				lastPitchTr=notes[choice]+scale;
				
				notesOutput[0]=notes[choice]+scale;
				volumeOutput[0]=volume[choice];
				
				OSC.main(noteArray,"/mididata");
//				Main.armHandling.receiveNote(noteArrayInt);
				
				int durationChoice = duration[choice];
				durationOutput[0]=duration[choice];
				
//				timer = new Timer();
//				timerNewNote = new TimerNewNote();
//				timer.schedule(timerNewNote, (int) (durationChoice*100/Main.stats.bpm));


	
			}
			else if (notes.length>6){
				pitchProbArray = new int[notes.length-4];
				for (int i=3;i<notes.length-4;i++){
					if (notes[i-1]==notesOutput[notesOutput.length-1]){
						pitchProbArray[i]=pitchProbArray[i]+1;
					}
					if (notesOutput.length>1){
						if (notes[i-1]==notesOutput[notesOutput.length-1]&&notes[i-2]==notesOutput[notesOutput.length-2]){
							pitchProbArray[i]=pitchProbArray[i]+100;
						}
					}
					if (notesOutput.length>2){
						if (notes[i-1]==notesOutput[notesOutput.length-1]&&notes[i-2]==notesOutput[notesOutput.length-2]&&notes[i-3]==notesOutput[notesOutput.length-3]){
						pitchProbArray[i]=pitchProbArray[i]+10000;
	//					System.out.println("*****************");
						}
					}
				}
				
				int choice=decision(pitchProbArray);
//				pointer = pointer + 1;
//				int choice = pointer;
				if(notes[choice]<30){
					System.out.println("ERROR on NOTEOUT: "+notes[choice]);
					choice =(int) (Math.random()*(notes.length-2)+1);
//					System.out.println("new note: "+notes[choice]);
				}
				
				int pitchChoice = notes[choice]+scale;
				pitch = PitchTranslation.translate(pitchChoice,lastPitch,lastPitchTr);
				lastPitch=pitch;
				lastPitchTr=pitchChoice;
				System.out.println("pitchOut="+pitch);
	//			System.out.println("count="+count);
				int volumeChoice = volume[choice];
				int durationChoice = duration[choice-1];
				
				while(pitch<48){
					pitch=pitch+12;
				}
				while(pitch>94){
					pitch=pitch-12;
				}
				
				Object[] noteArray = {pitch+12,volumeChoice};
//				int[] noteArrayInt = {notes[choice],volume[choice]};
				OSC.main(noteArray,"/mididata");
//				Main.armHandling.receiveNote(noteArrayInt);
				
				TimeTranslation timeTranslation=new TimeTranslation();
				timeTranslation.playbackDiff=durationChoice;
				timeTranslation.run();
				

							
				int[] temp = notesOutput;
				notesOutput = new int[notesOutput.length+1];
				System.arraycopy(temp, 0, notesOutput, 0, temp.length);
				notesOutput[notesOutput.length-1]=pitchChoice;
				
				temp = volumeOutput;
				volumeOutput = new int[volumeOutput.length+1];
				System.arraycopy(temp, 0, volumeOutput, 0, temp.length);
				volumeOutput[volumeOutput.length-1]=volume[choice];
				
				temp = durationOutput;
				durationOutput = new int[durationOutput.length+1];
				System.arraycopy(temp, 0, durationOutput, 0, temp.length);
				durationOutput[durationOutput.length-1]=duration[choice];
				
			}
			count=count+1; // update count
		}

		if (!stop)
		{
//			System.out.println("setting timer again wait for: "+(int) (waitTime));
			timer = new Timer();
			timerNewNote = new TimerNewNote();
			timer.schedule(timerNewNote, (int) (waitTime*100/Main.stats.bpm));
		}
	}
	public int decision(int[] valuesArray){
		int sum = sumValues(valuesArray);
		int countTotal = (int) (Math.random()*sum)+1;
		int index=0;
		int counter=0;
		while (counter<countTotal&&index<valuesArray.length-1){
			counter=counter+valuesArray[index];
			if (counter<countTotal){
				index=index+1;
			}
		}
		return index;
	}
	public int sumValues(int[] valuesArray){
		int sum=0;
		for (int i=0; i<valuesArray.length; i++){
			sum = sum+valuesArray[i];
		}	
		return sum;
	}
	
	public void incomingNote(int note){
		int[] temp = notesInput;
		notesInput = new int[notesInput.length+1];
		System.arraycopy(temp, 0, notesInput, 0, temp.length);
		notesInput[notesInput.length-1]=note;
	}
	public void decideStyle(){
		name = styles[decision(styleStrengths)];
	}
	public void updateNotesOut(int[] noteArray)
	{
		
		int[] temp = notesOutput;
		notesOutput = new int[notesOutput.length+1];
		System.arraycopy(temp, 0, notesOutput, 0, temp.length);
		notesOutput[notesOutput.length-1]=noteArray[0];
		
		temp = volumeOutput;
		volumeOutput = new int[volumeOutput.length+1];
		System.arraycopy(temp, 0, volumeOutput, 0, temp.length);
		volumeOutput[volumeOutput.length-1]=noteArray[1];
		
		temp = durationOutput;
		durationOutput = new int[durationOutput.length+1];
		System.arraycopy(temp, 0, durationOutput, 0, temp.length);
		durationOutput[durationOutput.length-1]=noteArray[2];
	}
}
